import chardet
import codecs
import tempfile
import os
from formats import FileFormat
import subprocess
import mutagen
import sys
from subprocess import STDOUT
from main import Setup


allowed_formats = ["BINARY", "MOTOROLA", "AIFF", "WAVE", "MP3"]
allowed_flags = ["DCP", "4CH", "PRE", "SCMS"]
allowed_datatypes = ["AUDIO", "CDG", "MODE1/2048", "MODE1/2352", \
"MODE2/2336", "MODE2/2352", "CDI/2336", "CDI/2352"]
option_snntool_unsupported_input="snntool_unsupported_input"
option_falback_to_wav="falback_to_wav"
 
__file_type__="cue"


class CUE(FileFormat):  

    
    def get_file_type():
        return __file_type__
    get_file_type = staticmethod(get_file_type)
    
    def get_input_convert_string(self):
        return 
    
    
    def convert_string():
        return "shnsplit"
    convert_string = staticmethod(convert_string)
    
    def get_image_file_name(self,cue):
        if os.path.exists(cue.image_file_name):
            return cue.image_file_name
        cuename = "".join(cue.file_name.split(".")[:-1]) + "."
        
        for name in [cuename + ext for ext in ["flac", "FLAC", "ape", "APE", "wv", "WV", "wav", "WAV","mp3","MP3"]]:
            if os.path.exists(name):
                return name
        return None
    
    
    def process_file(self,cue_file_name,output_format):
        print "output format ="+output_format.get_file_type()       
        output_extention=output_format.get_file_type()
        cue=CUE_SPLITTER(cue_file_name)
        if cue.image_file_name==None:
            print("ERROR: Image not found in "+cue.file_name)
            sys.exit()
        tmp_fname = cue.get_temporary_copy()
        ifn = self.get_image_file_name(cue)
        os.chdir(os.path.dirname(ifn))
        
        
        # 'cust ext=mp3 lame --quiet --preset cbr 320 - "%f"'
        # Splitting image into files
        #cmd = "shntool split "+escape_string(ifn)+" -f "+escape_string(tmp_fname)+" -o flac"
        
        codec=output_format.get_output_codec(self.get_file_type())
        print "got the codec="+codec
        
        if  sys.platform.startswith('win'):
            cmd = "shntool split -O always "+"\""+ifn+"\""" -f "+tmp_fname+" -o "+codec
        else:
            cmd = "shntool split -O always "+self.escape_string(ifn)+" -f "+self.escape_string(tmp_fname)+" -o "+codec    
        
        print (cmd)
        #sys.exit()
        return_code = 0
        
        #return_code = subprocess.Popen(cmd, shell=1)
        cmd=subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        streamdata = cmd.communicate()

        
        self.get_value("GENERAL",option_snntool_unsupported_input)
        if cmd.returncode!=0 and "none of the builtin format modules handle input file" in streamdata[1]:
            print "none of the builtin format modules handle input file."
            if self.get_boolean_value("GENERAL",option_falback_to_wav):
                print "Perform fallback to wav to proceed"
                converter=main.Converter()
                converter.convert_single_file(ifn)
                
            
        if cmd.returncode!=0:
            print "We fail to convert given "+ifn
            sys.exit
        # Stop process if splitting failed
        if cmd.returncode!=0:
            return
        if os.path.exists("split-track00.flac"):
            print("Removing split-track00.flac")
            os.remove("split-track00.flac")
        
        # Writing tags into splitted files & renaming them
        for track in cue.tracks:
            if not track.number==None:
                src_file_name = "split-track"+str(track.number).zfill(2)+"."+output_extention.lower()
                dst_file_name = str(track.number).zfill(2)+' - '+track.title+"."+output_extention.lower()
                print ("Write tags for the "+dst_file_name+"\n")
                #audio = FLAC(src_file_name)
                audio=mutagen.File(src_file_name, easy=True)
                if not track.title==None:
                    audio["title"] = track.title
                #if not track.performer==None:
                #    audio["artist"] = track.performer
                #else:
                if ("artist" in audio) and (cue.performer!=None):
                    audio["artist"] = cue.performer
                if ("tracknumber" in audio) and (not track.number==None):
                    audio["tracknumber"] = str(track.number)
                if ("album" in audio) and (not cue.title==None):
                    audio["album"] = cue.title
                if ("isrc" in audio) and (not track.isrc==None):
                    audio["isrc"] = track.isrc
                if ("genre" in audio) and (not cue.genre==None):
                    audio["genre"] = cue.genre
                if ("date" in audio) and (not cue.date==None):
                    audio["date"] = cue.date
                if ("discid" in audio) and (not cue.discid==None):
                    audio["discid"] = cue.discid
                if ("comment" in audio) and (not cue.comment==None):
                    audio["comment"] = cue.comment
                # 0th track left blank
                if ("tracktotal" in audio): 
                    audio["tracktotal"] = str(len(cue.tracks) - 1)
                audio.pprint()
                audio.save()
                os.chdir(os.path.dirname(ifn))
                os.rename(src_file_name, dst_file_name)  
        os.remove(tmp_fname)
        
            
class Track:
    def __init__(self):
        self.flags = []
        self.indexes = []
        self.isrc = None
        self.performer = None
        self.pregap = None
        self.postgap = None
        self.songwriter = None
        self.title = None
        self.number = None
        self.datatype = None


class CUE_SPLITTER:    
    def __init__(self, file_name):
        self.file_name = file_name
        self.content = None
        self.load()
        self.parse()
        
    def __str__(self):
        return self.content
        
    def load(self):
        f = open(self.file_name, 'r')
        self.file_encoding = chardet.detect(''.join(f.readlines()))['encoding']
        f.close()
        f = codecs.open(self.file_name, encoding = self.file_encoding, \
                            mode = 'r')
        self.content = f.readlines()
        self.content = [ x.replace("/","\\") for x in self.content]
        f.close()
        
    def parse(self):
        scope = 'global'
        # Initilizing attributes
        self.tracks = []
        self.remarks = []
        self.catalog_number = None
        self.cdtext_file_name = None
        self.image_file_format = None
        self.image_file_name = None
        self.performer = None
        self.songwriter = None
        self.title = None
        self.genre = None
        self.date = None
        self.discid = None
        self.comment = None
        # Leaving first track blank
        current_track = Track()
        stripped_content = [l.strip() for l in self.content]
        # Parsing all posible lines
        for line in stripped_content:
            cmd = line.split(" ")[0]
            if cmd=="CATALOG":
                self.catalog_number = line.split(" ")[1]
                if not len(self.catalog_number)==13:
                    print("WARNING: Catalog number has incorrect length")
            if cmd=="CDTEXTFILE":
                value = line.split(" ")[1]
                if value[0] == '"': value = value[1:]
                if value[-1] == '"': value = value[:-1]
                self.cdtext_file_name = value
            if cmd=="FILE":
                file_name_value = line[5:]
                format_value = file_name_value.split(" ")[-1]
                self.image_file_format = format_value.upper()
                z = len(format_value) + 1 # +1 is for space
                file_name_value = file_name_value[:-z]
                if file_name_value[0] == '"':
                    file_name_value = file_name_value[1:]
                if file_name_value[-1] == '"':
                    file_name_value = file_name_value[:-1]
                # Add dirname of CUE file if path to image is relative
                if os.path.dirname(file_name_value)=="":
                    file_name_value = os.path.join( \
                            unicode(os.path.dirname(self.file_name), 'UTF-8'), \
                            unicode(file_name_value))
                self.image_file_name = file_name_value
                if not self.image_file_format in allowed_formats:
                    print("WARNING: Image format %s is not allowed" % \
                    self.image_file_format)
            if cmd=="FLAGS":
                current_track.flags = [x.upper() for x in line.split(" ")[1:]]
                for flag in current_track.flags:
                    if not self.image_file_format in allowed_formats:
                        print("WARNING: Flag %s is not allowed" % flag)
            if cmd=="INDEX":
                current_track.indexes.append(\
                (line.split(" ")[1], line.split(" ")[2]))
                if int(line.split(" ")[1])<0 or int(line.split(" ")[1])>99:
                    print("WARNING: Index number %s is not allowed" % \
                    line.split(" ")[1])
            if cmd=="ISRC":
                current_track.isrc = line.split(" ")[1]
                if not len(line.split(" ")[1]) == 12:
                    print("WARNING: ISRC must be 12 characters in length")
            if cmd=="PERFORMER":
                value = line[11:]
                if value[0] == '"': value = value[1:]
                if value[-1] == '"': value = value[:-1]
                if scope=="global":
                    self.performer = value
                if scope=="track":
                    current_track.performer = value
                if len(value)>80:
                    print("WARNING: Performer name should be limited \
                    to 80 character or less")
            if cmd=="POSTGAP":
                current_track.postgap = line.split(" ")[1]
            if cmd=="PREGAP":
                current_track.pregap = line.split(" ")[1]
            if cmd=="REM":
                # TODO: Implement custom encoders' tags written as REMs
                self.remarks.append(line[4:])
            if line.startswith("REM GENRE"):
                self.genre = line[10:]
            if line.startswith("REM DATE"):
                self.date = line[9:]
            if line.startswith("REM DISCID"):
                self.discid = line[11:]
            if line.startswith("REM COMMENT"):
                value = line[11:]
                if value[0] == '"': value = value[1:]
                if value[-1] == '"': value = value[:-1]
                self.comment = value
            if cmd=="SONGWRITER":
                value = line[11:]
                if value[0] == '"': value = value[1:]
                if value[-1] == '"': value = value[:-1]
                if scope=="global":
                    self.songwriter = value
                if scope=="track":
                    current_track.songwriter = value
                if len(value)>80:
                    print("WARNING: Songwriter name should be limited \
                    to 80 character or less")
            if cmd=="TITLE":
                value = line[6:]
                if value[0] == '"': value = value[1:]
                if value[-1] == '"': value = value[:-1]
                if scope=="global":
                    self.title = value
                if scope=="track":
                    current_track.title = value
                if len(value)>80:
                    print("WARNING: Title should be limited \
                    to 80 character or less")
            if cmd=="TRACK":
                scope = "track"
                self.tracks.append(current_track)
                current_track = Track()
                current_track.number = int(line.split(" ")[1])
                current_track.datatype = line.split(" ")[2].upper()
                if current_track.number<1 or current_track.number>99:
                    print("WARNING: Track number must be between 1 and \
                    99 inclusive")
                if not current_track.datatype in allowed_datatypes:
                    print("WARNING: Track datatype %s is not allowed" \
                    % current_track.datatype)
        self.tracks.append(current_track)
                    
    def get_temporary_copy(self):
        tempdir=tempfile.gettempdir()
        (fd, fname) = tempfile.mkstemp(suffix='.cue', prefix='tmp', dir=tempdir, text=True)
        f = codecs.open(fname, encoding='utf-8', mode='w')
        for line in self.content:
            f.write(line)
        f.close()
        os.close(fd)
        return fname
